package com.company.笔试.xml生成器;

import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.apache.commons.lang.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * @ClassName Node
 * @Description TODO
 * @Author 11
 * @Date 2021/4/7 9:53
 * @Version 1.0
 */
@Setter
@Getter
@Accessors(chain = true)
public class Node {
    /**
     * 节点名称
     */
    private String name;

    /**
     * 节点Id
     */
    private String id;

    /**
     * 节点描述
     */
    private String description;

    /**
     * 子节点
     */
    private List<Node> childNodes = new ArrayList<>();

    /**
     * 父节点
     */
    private Node parentNode;


    /**
     * 添加子节点
     * @param childNode
     */
    public void setChildNode(Node childNode){
        if (childNode.getParentNode() == null){
            throw new RuntimeException("加入的子节点不存在父节点，设置失败！");
        }
        List<Node> nodes = childNode.getParentNode().getChildNodes();
        if (!nodes.isEmpty()){
            Optional<Node> optional = nodes.stream().filter(n -> n.getName().equals(childNode.getName())).findFirst();
            if (optional.isPresent()){
                throw new RuntimeException("父节点" + childNode.getParentNode().getName() + "已存在" + optional.get().getName() +"节点了，添加失败!");
            }
        }
        nodes.add(childNode);
        childNode.getParentNode().setChildNodes(nodes);
    }

    /**
     * 查找到顶端节点
     * @return
     */
    public Node findParentNode(){
        Node parentTemp = parentNode == null ? this : parentNode;
        while (parentTemp.getParentNode() != null){
            parentTemp = parentTemp.getParentNode();
        }
        return parentTemp;
    }

    /**
     * 层次遍历xml树结构
     * 如果传入的参数不为null,则遍历当前节点有方法能打印当前节点和所有子节点（包括子孙节点）的内容
     * @param n
     */
    public void printNodeInfo(Node n){
        Node root = null;
        if (n != null){
            root = n;
        }else {
            //获取顶端root节点
            root = findParentNode();
        }
        MyQueue queue = new MyQueue();
        //根节点先被访问,入队
        queue.insert(root);
        while (!queue.isEmpty()){
            Node temp = (Node) queue.remove();
            System.out.println(temp.getName() + "--------->" +(temp.getParentNode() == null? "不存在父节点":"父节点为：" + temp.getParentNode().getName()));
            List<Node> nodes = temp.getChildNodes();
            if (!nodes.isEmpty()){
                for (Node node : nodes) {
                    //入队
                    queue.insert(node);
                }
            }
        }
    }

    /**
     * 递归删除关联节点
     * @param node
     */
    public static void removeNode(Node node){
        //该节点的子节点
        List<Node> nodes = node.getChildNodes();
        if (!nodes.isEmpty()){
            List<Node> tempNodes = new ArrayList<>(nodes);
            for (Node n : tempNodes) {
                removeNode(n);
            }
        }
        //移除对应的父节点里面的子节点
        Node parentNode = node.getParentNode();
        if (parentNode != null){
            List<Node> childNodes = parentNode.getChildNodes();
            childNodes.remove(node);
            node.getParentNode().setChildNodes(childNodes);
        }
        node.setParentNode(null);
    }

    /**
     * 递归构建xml文件格式
     * @return
     */
    public static String createXml(Node node){
        StringBuilder builder = new StringBuilder();
        if (!StringUtils.isEmpty(node.getName())){
            builder.append("<").append(node.getName());
            if (!StringUtils.isEmpty(node.getId())){
                builder.append(" ID=\"").append(node.getId()).append("\"");
            }
            builder.append(">").append("\r\n");
            if (!StringUtils.isEmpty(node.getDescription())){
                builder.append(node.getDescription()).append("\r\n");
            }
            //获取该节点的子节点
            List<Node> childNodes = node.getChildNodes();
            if (!childNodes.isEmpty()){
                for (Node childNode : childNodes) {
                    //递归调用
                    builder.append(createXml(childNode));
                }
            }
            builder.append("</").append(node.getName()).append(">").append("\r\n");
        }
        return builder.toString();

    }

}
